﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using SoftSource.Common;
using SoftSource.MVVMC;
using SoftSource.Reactive;
using SoftSource.Timecard.Resources;
using SoftSource.Timecard.ViewModelInterfaces;
using SoftSource.Timecard.Web.Data;

namespace SoftSource.Timecard.Views
{
    public sealed partial class UpdateReminderView : UserControl, IView<IUpdateReminderViewModelConsume>
    {
        #region Fields

        private Func<LastEntry, Reminder> reminderSelector;
        private Filter<Reminder> reminderFilter;
        private ObservableCollection<Reminder> reminders;
        private string defaultMessage = "Hi all,{0}{0}If you haven’t already, please update your timecard through {1} as soon as possible. I need to bill the customers.{0}{0}Thanks,{0}-{2}";

        #endregion Fields

        public UpdateReminderView()
        {
            InitializeComponent();

            this.reminders = new ObservableCollection<Reminder>();
            this.reminderSelector = entry =>
                {
                    Reminder reminder = new Reminder();

                    reminder.UserID = entry.UserID;
                    reminder.Name = entry.Name;
                    reminder.LastEntryDate = entry.EntryDate;

                    return reminder;
                };

            Loaded += new RoutedEventHandler(UpdateReminderView_Loaded);
        }

        #region Events

        void UpdateReminderView_Loaded(object sender, RoutedEventArgs e)
        {
            if (this.ViewModel != null)
            {
                this.Busy.BusyContent = ApplicationStrings.LoadingMessage;
                this.Busy.IsBusy = true;

                this.ViewModel.Load // Load the data required to use this ViewModel
                    .Nullable()
                    .Subscribe(unit => this.Busy.IsBusy = false);

                this.ViewModel.Entries.Subscribe(this.RefreshEntries);

                if (this.ViewModel.Entries.Value != null && this.ViewModel.Entries.Value.Count() > 0)
                    this.RefreshEntries(this.ViewModel.Entries.Value);
            }
        }

        private void RefreshEntries(IEnumerable<LastEntry> entries)
        {
            if (entries == null)
                return;

            this.reminders.Populate(entries.Select(this.reminderSelector));
            this.Reminders = new PagedCollectionView(this.reminders);
            this.Reminders.SortDescriptions.Add(new SortDescription(
                ObjectReflection.GetPropertyName<Reminder>(r => r.Name),
                ListSortDirection.Ascending));

            this.ReminderDataGrid.ItemsSource = this.Reminders;
            this.SetDefaultMessage(DateTime.Now);
            this.All_CheckChanged(null, null);

            this.reminderFilter = this.Reminders.AttachFilter<Reminder>();
            this.reminderFilter.Add(reminder =>
                {
                    if (this.CutoffDatePicker.SelectedDate.HasValue)
                    {
                        return reminder.LastEntryDate < this.CutoffDatePicker.SelectedDate.Value;
                    }

                    return true;
                });
            this.reminderFilter.Refresh.TryInvoke();
        }

        private void Send_Click(object sender, RoutedEventArgs e)
        {
            if (this.ViewModel != null)
            {
                ChildWindow cw = new ChildWindow();
                cw.Title = "Please enter your password";
                cw.MinWidth = 200;
                cw.HasCloseButton = false;

                var ui = this.ViewModel.CreateGetUserPasswordView(observable => observable
                    .Do(password => cw.Close())
                    .Where(password => !string.IsNullOrEmpty(password))
                    .Do(password => this.Send(password))
                    .Subscribe());

                if (ui != null)
                {
                    cw.Content = ui;
                    cw.Show();
                }
            }
        }

        private void Send(string password)
        {
            var ids = from r in this.reminders
                      where r.SendReminder
                      select r.UserID;

            string message = this.messageTextBox.Text;

            if (!ids.IsNullOrEmpty())
            {
                this.Busy.BusyContent = ApplicationStrings.ActivitySendingReminderEmail;
                this.Busy.IsBusy = true;

                this.ViewModel.SendReminders(password, ids, message)
                    .Subscribe(unit => this.Busy.IsBusy = false);
            }
        }

        private void All_CheckChanged(object sender, RoutedEventArgs e)
        {
            if (!this.reminders.IsNullOrEmpty())
            {
                bool send = this.AllCheckbox.IsChecked ?? false;
                foreach (var reminder in this.reminders)
                {
                    reminder.SendReminder = send;
                }
            }
        }

        private void CutoffDatePicker_SelectedDateChanged(object sender, SelectionChangedEventArgs e)
        {
            this.reminderFilter.Refresh.TryInvoke();
            this.SetDefaultMessage(CutoffDatePicker.SelectedDate ?? DateTime.Now);
        }

        #endregion Events

        #region Properties

        public PagedCollectionView Reminders { get; set; }

        #endregion Properties

        #region Methods

        private void SetDefaultMessage(DateTime date)
        {
            string formattedMessage = string.Format(
                this.defaultMessage,
                Environment.NewLine,
                date.ToShortDateString(),
                WebContext.Current.User.FullName);
            this.messageTextBox.Text = formattedMessage;
        }

        #endregion Methods

        #region IView<IUpdateReminderViewModelConsume> Members

        public IUpdateReminderViewModelConsume ViewModel
        {
            get { return this.DataContext as IUpdateReminderViewModelConsume; }
            set { this.DataContext = value; }
        }

        #endregion

        public class Reminder : INotifyPropertyChanged
        {
            #region Fields
            private bool sendReminder;
            private int userID;
            private string name;
            private DateTime lastEntryDate;
            #endregion Fields

            public Reminder()
            {
                this.SendReminder = false;
            }

            #region INotifyPropertyChanged Members

            public event PropertyChangedEventHandler PropertyChanged;

            #endregion

            public bool SendReminder
            {
                get { return this.sendReminder; }
                set
                {
                    this.sendReminder = value;
                    this.PropertyChanged.Notify(() => this.SendReminder);
                }
            }

            public int UserID
            {
                get { return this.userID; }
                set
                {
                    this.userID = value;
                    this.PropertyChanged.Notify(() => this.UserID);
                }
            }

            public string Name
            {
                get { return this.name; }
                set
                {
                    this.name = value;
                    this.PropertyChanged.Notify(() => this.Name);
                }
            }

            public DateTime LastEntryDate
            {
                get { return this.lastEntryDate; }
                set
                {
                    this.lastEntryDate = value;
                    this.PropertyChanged.Notify(() => this.LastEntryDate);
                }
            }
        }
    }
}
